package com.start_eternity.oasissafewalk.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.start_eternity.oasissafewalk.mapper.StationMapper;
import com.start_eternity.oasissafewalk.pojo.*;
import com.start_eternity.oasissafewalk.pojo.dto.StationDTO;
import com.start_eternity.oasissafewalk.service.LoggService;
import com.start_eternity.oasissafewalk.service.StationService;
import com.start_eternity.oasissafewalk.utils.CalculateDistance;
import com.start_eternity.oasissafewalk.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class StationServiceImpl implements StationService {

    @Autowired
    public StationMapper stationMapper;
    @Autowired
    private LoggService loggService;
    @Autowired
    private HttpServletRequest request;


    private static final double MAX_DISTANCE = 5.0; // 5公里



    /*//查询站点
    @Override
    public List<Station> list() {
        return stationMapper.list();
    }*/
    @Override
    public PageBean page(Integer page, Integer pageSize, String stationName, Short stationStatus, LocalDate begin, LocalDate end) {
        //用logg记录
        Logg logg = new Logg();
        logg.setLoggTime(LocalDateTime.now());//记录执行的当前时间
        //获取请求头中的jwt令牌, 解析令牌
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);
        String name = (String) claims.get("username");
        logg.setLoggName(name);//记录执行者的名字
        logg.setLoggDescription("执行了查询线路的操作");//记录执行的具体操作
        loggService.insert(logg);//调用loggService接口将logg类的信息记录到数据库里面

        //1.设置分页参数
        PageHelper.startPage(page,pageSize);

        //2.执行查询
        List<Station> stationList = stationMapper.list(stationName, stationStatus, begin, end);
        Page<Station> p = (Page<Station>) stationList;

        //3.封装PageBean对象
        PageBean pageBean = new PageBean(p.getTotal(),p.getResult());

        return pageBean;
    }

    //添加站点
    @Override
    public void add(Station station) {

        //用logg记录
        Logg logg = new Logg();
        logg.setLoggTime(LocalDateTime.now());//记录执行的当前时间
        //获取请求头中的jwt令牌, 解析令牌
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);
        String name = (String) claims.get("username");
        logg.setLoggName(name);//记录执行者的名字
        logg.setLoggDescription("执行了添加站点的操作，此次添加站点id为:"+ station.getStationId());//记录执行的具体操作
        loggService.insert(logg);//调用loggService接口将logg类的信息记录到数据库里面

        station.setCreateTime(LocalDateTime.now());
        station.setUpdateTime(LocalDateTime.now());

        stationMapper.insert(station);
    }

    //删除站点
    @Override
    public void delete(Integer id) {

        //用logg记录
        Logg logg = new Logg();
        logg.setLoggTime(LocalDateTime.now());//记录执行的当前时间
        //获取请求头中的jwt令牌, 解析令牌
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);
        String name = (String) claims.get("username");
        logg.setLoggName(name);//记录执行者的名字
        logg.setLoggDescription("执行了删除站点的操作，此次删除站点id为:"+ id);//记录执行的具体操作
        loggService.insert(logg);//调用loggService接口将logg类的信息记录到数据库里面

        stationMapper.deleteById(id);
    }

    //根据站点id获取Station站点对象
    @Override
    public Station getById(Integer id) {
        return stationMapper.getById(id);
    }

    //修改站点
    @Override
    public void update(Station station) {

        //用logg记录
        Logg logg = new Logg();
        logg.setLoggTime(LocalDateTime.now());//记录执行的当前时间
        //获取请求头中的jwt令牌, 解析令牌
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);
        String name = (String) claims.get("username");
        logg.setLoggName(name);//记录执行者的名字
        logg.setLoggDescription("执行了修改站点的操作，此次修改的站点id为:"+ station.getStationId());//记录执行的具体操作
        loggService.insert(logg);//调用loggService接口将logg类的信息记录到数据库里面

        station.setUpdateTime(LocalDateTime.now());

        stationMapper.update(station);
    }





    //获取里订单距离最近的站点的索引
    public int getIndex(double[] arr){
        double min = arr[0];
        int result = 0;
        if (min == 0){
            for (int i = 1; i < arr.length; i++) {
                min = arr[i];
                if (min != 0){
                    result = i;
                    break;
                }
            }
        }
        int index = 0;
        for (int i = result + 1; i < arr.length; i++) {
            if((arr[i] < min) && (arr[i] != 0)){
                min = arr[i];
                index = i;
            }
        }
        return index;
    }


    //判断有无满足订单的站点，如果有，就返回最合适的站点，如果无就为空
    @Override
    public StationDTO getStationDTO(Order order) {

        StationDTO stationDTO = new StationDTO();
        //获取所有站点的数据
        List<Station> allStation = stationMapper.getStation();

        //符合订单的开始站点
        List<Station> startStation = new ArrayList<>();
        //符合订单的结束站点
        List<Station> endStation = new ArrayList<>();

        //将符合订单的站点放入startStation集合和endStation集合中
        for (Station station : allStation) {
            double startDistance = CalculateDistance.calculateDistance(order.getStartLatitude(), order.getStartLongitude(), station.getLatitude(), station.getLongitude());
            double endDistance = CalculateDistance.calculateDistance(order.getEndLatitude(), order.getEndLongitude(), station.getLatitude(), station.getLongitude());
            if (startDistance <= MAX_DISTANCE) {
                startStation.add(station);
            }
            if (endDistance <= MAX_DISTANCE) {
                endStation.add(station);
            }
        }


        /*
        //离订单最近的站点

        if(!startStation.isEmpty()){
            //创建数组，将符合订单的起始站点离订单位置的距离放入数组中
            double[] start = new double[startStation.size()];
            for (int i = 0; i < startStation.size(); i++) {
                double startDistance = calculateDistance(
                        order.getStartLatitude(), order.getStartLongitude(),
                        startStation.get(i).getLatitude(), startStation.get(i).getLongitude());
                start[i] = startDistance;
            }
            //获取离订单最近的起始站点的索引
            int startMinIndex = getIndex(start);

            //将离订单最近的起始站点放入stationDTO中
            stationDTO.setStartStation(startStation.get(startMinIndex));
        }

        if (!endStation.isEmpty()){
            //创建数组，将符合订单的结束站点离订单位置的距离放入数组中
            double[] end = new double[endStation.size()];
            for (int i = 0; i < endStation.size(); i++) {
                double endDistance = calculateDistance(
                        order.getEndLatitude(), order.getEndLongitude(),
                        endStation.get(i).getLatitude(), endStation.get(i).getLongitude());
                end[i] = endDistance;
            }
            //获取离订单最近的结束站点的索引
            int endMinIndex = getIndex(end);

            //将离订单最近的结束站点放入stationDTO中
            stationDTO.setEndStation(endStation.get(endMinIndex));
        }*/

        //线路最短的站点
        if((!startStation.isEmpty()) && (!endStation.isEmpty())){
            double[] range = new double[startStation.size() * endStation.size()];
            for (int i = 0; i < startStation.size(); i++) {
                for (int j = 0; j < endStation.size(); j++) {
                    double distance = CalculateDistance.calculateDistance(startStation.get(i).getLatitude(), startStation.get(i).getLongitude(),
                            endStation.get(j).getLatitude(), endStation.get(j).getLongitude());
                    range[i * endStation.size() + j] = distance;
                }
            }

            int minIndex = getIndex(range);
            if ( minIndex < endStation.size()){
                int startIndex = 0;
                stationDTO.setStartStation(startStation.get(startIndex));
                stationDTO.setEndStation(endStation.get(minIndex));
            }
            if ( minIndex > endStation.size()){
                int startIndex = minIndex / endStation.size();
                int endIndex = minIndex % endStation.size();
                stationDTO.setStartStation(startStation.get(startIndex));
                stationDTO.setEndStation(endStation.get(endIndex));
            }

        }


        return stationDTO;
    }

}
